#![no_std]
#![no_main]

extern crate axplat_aarch64_dyn;

#[macro_use]
extern crate axstd as std;
#[macro_use]
extern crate log;

use arceos_ext::iomap;
use core::time::Duration;
use some_serial::{DataBits, FlowControl, Parity, StopBits, UartConfig, pl011};
use std::thread::sleep;

const UART2_BASE: usize = 0x2800E000;
const UARTCLK: usize = 100_000_000; // 100 MHz

#[unsafe(no_mangle)]
fn main() {
    let uart_virt = iomap(UART2_BASE.into(), 0x1000).unwrap();

    let mut uart = pl011::new(uart_virt, UARTCLK);

    uart.configure(&UartConfig {
        baud_rate: 57600,
        data_bits: DataBits::Eight,
        stop_bits: StopBits::One,
        parity: Parity::None,
        flow_control: FlowControl::None,
    })
    .unwrap();

    uart.enable();

    let mut rx = uart.try_take_rx().unwrap();
    let mut tx = uart.try_take_tx().unwrap();

    // let data: [u8; 10] = [0x05,0x44,0x21,0x00,0x31,0x00,0x00,0x01,0x00,0x01];
    // tx.write(&data).unwrap();

    info!("UART initialized");

    loop {
        info!("=== Send Data ===");
        let data: [u8; 14] = [0x05, 0x44, 0x23, 0x18, 0x33, 0x18, 0x00, 0x64, 0x00, 0x64, 0x9d, 0x38, 0xf1, 0xcf];
        let mut sent = 0;
        while sent < data.len() {
            match tx.write(&data[sent..]) {
                Ok(n) if n > 0 => sent += n,
                _ => {} // busy, waiting UART FIFO
            }
        }
        info!("Send {} bytes: {:?}", sent, &data[..]);

        info!("=== Receive Data ===");
        let mut buf = [0u8; 64];
        let n = rx.read(&mut buf).unwrap_or_else(|_e| 0);
        if n > 0 {
            info!("Received {} bytes: {:?}", n, &buf[..n]);
        }
    }
}
